<?php
declare(strict_types=1);

namespace txz\common\third_lib\model\util;

define("TXZ_ROOT_DIR", '/data/web/server/');
$require_path_arr = [
    TXZ_ROOT_DIR . 'common/conf/FileConfig.php'
];
foreach ($require_path_arr as $path){
    require_once $path . '';
}

use ErrorException;

/**
 * Class Service
 */
class Service{
    private $file;
    private $cmd;
    private $check_cmd;

    /**
     * Service constructor.
     * @param $argv
     */
    public function __construct($argv)
    {
        $this->file = $argv[1];
        $this->cmd = $argv[2] ?? 'check';
        $this->check_cmd = 'ps -ef | grep ' . $this->file . '| grep -v grep | grep -v service | grep -v Service | grep -v Linux_task | grep -v source ';
    }

    public function run(){
//        echo "cmd : " . '$this->'.$this->cmd.'();';
        eval('$this->'.$this->cmd.'();');
    }

    public function restart(){
        $this->stop();
        $this->start();
    }

    public function stop(){
        $cmd = $this->check_cmd . '| awk \'{print $2}\' | xargs kill -9';
        system($cmd);
        echo "stop ok\n";
    }

    /**
     * @param $exe
     * @return string
     */
    private function get_start_cmd($exe){
        $cmd = 'nohup ' . $exe . ' ' . $this->file . " &> " . $this->file . "_.log &";
        return $cmd;
    }

    public function start(){
        $fileArr = explode('.', $this->file);
        $ext = $fileArr[count($fileArr)-1];
        $cmdArr = [];
        $res = '';
        if ($ext === 'php'){
            $cmdArr[] = $this->get_start_cmd('php');
            $cmdArr[] = $this->get_start_cmd('php7');
        } else if($ext === 'py'){
            $cmdArr[] = $this->get_start_cmd('python');
            $cmdArr[] = $this->get_start_cmd('python2');
            $cmdArr[] = $this->get_start_cmd('python3');
        }

        foreach ($cmdArr as $cmd){
            try{
                $this->cmd_file($cmd);
                break;
            }catch (\Throwable $e){
                continue;
            }
        }
        if (!$res){
            echo "start ok\n";
        }else{
            die('start fail');
        }
    }

    public function check(){
        exec($this->check_cmd, $arr);
        if(count($arr) <= 0){
            $this->restart();
        }
    }

    /**
     * @param $shell_cmd
     * @return mixed
     * @throws ErrorException
     * @internal param $cmd
     */
    private function cmd_file($shell_cmd){
        $cmd = addslashes($shell_cmd);
        $cmdArr = explode(' ', $cmd);
        $exe_file_path = $cmdArr[2];
        $exe = $cmdArr[1];

        if($this->path_is_py($exe_file_path) && $exe === 'python3'){
            $this->py_specail($exe_file_path);
        }

        $file_content = "
#!/bin/sh
. /etc/profile && . ~/.bash_profile
" . $cmd;

        $path = '/tmp/r_' . random_int(0, 100000);
        file_put_contents($path, $file_content);
        chmod($path,0777);
        shell_exec("sh " . $path);
        unlink($path);
        sleep(1);
        exec("ps -ef | grep $exe_file_path | grep -v grep | grep -v Service.php ", $arr);
        if (!$arr){
            throw new ErrorException();
        }
    }

    /**
     * @param $exe_file_path
     * @return bool
     */
    private function path_is_py($exe_file_path){
        $arr = explode('.', $exe_file_path);
        if ($arr[count($arr)-1]=== 'py'){
            return True;
        }else{
            return False;
        }
    }


    private $has_handle_py_file_set = [];
    /**
     * @param $exe_file_path
     */
    private function py_specail($exe_file_path){
        $index = array_search($exe_file_path, $this->has_handle_py_file_set);
        if ($index !== false){
            return;
        }else{
            $this->has_handle_py_file_set[] = $exe_file_path;
        }
        $add_string = <<<EOF
import sys
import os
path = os.path.dirname(os.path.abspath(sys.argv[0]).replace('\\\\', '/')) + '/'
for i in range(1, len(path.split('/')) - 2):
    sys.path.append(path + '../' * i)
EOF;
        $lines = [];
        $exe_file = fopen($exe_file_path, 'r');
        while(feof($exe_file)){
            $line = fgets($exe_file, 4096);
            if(
                Util::startWitsh($line, 'import sys') ||
                Util::startWitsh($line, 'import os') ||
                Util::startWitsh($line, 'path = os.path.dirname') ||
                Util::startWitsh($line, 'for i in range(1, len(path.spl') ||
                Util::startWitsh($line, '    sys.path.append(pa')
            ){
                continue;
            } else {
                $lines[] = $line;
            }
        }
        fclose($exe_file);
        $content = $add_string . join("", $lines);
        file_put_contents($exe_file_path, $content);
    }
}

(new Service($argv))->run();
